/*
 * scubuf.h, buffers for SmartCam skeleton system
 */

#ifndef __SCU_SCUBUF_H
#define __SCU_SCUBUF_H

#include <stdio.h>
#include <timer.h>
#include <scos.h>

#ifdef __cplusplus
extern "C" {
#endif

//#define SCU_BUF_CANARY 0x12345678
#define SCU_BUF_CHECK_CANARY(buf) if ((buf)->canary != SCU_BUF_CANARY) { if ((buf)->canary == ~SCU_BUF_CANARY) abortErrorl((STREAM(scul_buf.crit), "Buffer %p's canary is dead", buf)) else abortErrorl((STREAM(scul_buf.crit), "Buffer %p's canary is mangled", buf)) }

#define SCU_BUF_PATH  "/var/tmp"

#ifndef UINT_FAST8_MAX
#define UINT_FAST8_MAX 255
#endif /* UINT_FAST8_MAX */

#define SCU_BUF_MAX_READERS UINT_FAST8_MAX

#define SCU_BUF_OPTION_WRITETODISK 0

#define SCU_BUF_BLOCK_ALL 1
#define SCU_BUF_BLOCK_ANY 2

typedef struct scu_bufptr_s
{
  int ptr, newptr;
} scu_bufptr_t;

typedef int_fast8_t scu_bufptrid_t;
 
struct scu_buf_s;
typedef void (*buf_destructor_t)(struct scu_buf_s *);
typedef struct scu_buf_s
{
#ifdef SCU_BUF_CANARY
  int canary;
#endif
  scu_bufptr_t *reader, writer;
  uint_fast8_t readers, maxreaders;
  
  uint8_t *data;
  int size, unit;
  unsigned long int total;
  tmr_t timer;
  
  scos_mutex_t lock, readlock, writelock;
  scos_cond_t readcondition, writecondition;
  uint_fast8_t locked, references, finalized;

  buf_destructor_t destructor;
  int counter;
  FILE *file;
  int index;
  int waits;
} scu_buf_t;

int scuBufferSetGlobalOption(int option, int value);
scu_buf_t scuBufferCreate(int size, uint_fast8_t maxreaders,
			  buf_destructor_t destructor);
int scuBufferSetIndex(scu_buf_t *buf, int index);
int scuBufferRemoveReference(scu_buf_t *buf);
int scuBufferFinalize(scu_buf_t *buf);
int scuBufferIsDry(scu_buf_t *buf, scu_bufptrid_t ptr);
scu_bufptrid_t scuBufferAddReader(scu_buf_t *buf);
int scuBufferUnlock(scu_buf_t *buf);
int scuBufferSpaceAvailable(scu_buf_t *buf);
int scuBufferWrite(scu_buf_t *buf, void *data, int size, int options);
int scuBufferDataAvailable(scu_buf_t *buf, scu_bufptrid_t r);
int scuBufferRead(scu_buf_t *buf, scu_bufptrid_t r, void *data, int size,
                  int options);

int  scuBufferAllocate(scu_buf_t *buf, void **data, int size, int options);
void scuBufferReleaseAllocated(scu_buf_t *buf, int size);
int  scuBufferPeek(scu_buf_t *buf, scu_bufptrid_t r, void **data, int size,
                   int options);
void scuBufferReleasePeeked(scu_buf_t *buf, scu_bufptrid_t r, int size);

#ifdef __cplusplus
}
#endif

#endif /* __SCU_BUFFERS_H */
